﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace UnityEngine.EventSystems
{
	public abstract class PointerInputModuleE: PointerInputModule
	{

		private readonly MouseState m_MouseState = new MouseState();
		protected int mStackIdCache = 0;
		protected new PointerEventData GetLastPointerEventData(int id)
		{
			PointerEventData data;
			this.GetPointerData(id, out data, false, mStackIdCache);
			return data;
		}

		public override bool IsPointerOverGameObject(int pointerId)
		{
			
			var result = IsPointerOverGameObject_(pointerId);
			return result;
		}

		private bool IsPointerOverGameObject_(int pointerId)
		{
			PointerEventData pointerEventData = this.GetLastPointerEventData(pointerId);
			if (pointerEventData != null)
				return (Object)pointerEventData.pointerEnter != (Object)null;
			return false;
		}
		public void SetStackIdCache(int v)
		{
			mStackIdCache = v;
		}


		protected bool GetPointerData(int id, out PointerEventData data, bool create, int stackId)
		{
			var idOffset = stackId * 10000 + 100;
			id += idOffset;
			return GetPointerData(id, out data, create);
		}

		protected MouseState GetMousePointerEventDataNextRaycast(int id, PointerEventData leftData, bool removeInResult = false)
		{

			var raycast = FindFirstRaycast(m_RaycastResultCache);
			leftData.pointerCurrentRaycast = raycast;
			//m_RaycastResultCache.Clear();
			if (removeInResult)
			{
				m_RaycastResultCache.Remove(raycast);
			}

			// copy the apropriate data into right and middle slots
			PointerEventData rightData;
			GetPointerData(kMouseRightId, out rightData, true);
			CopyFromTo(leftData, rightData);
			rightData.button = PointerEventData.InputButton.Right;

			PointerEventData middleData;
			GetPointerData(kMouseMiddleId, out middleData, true);
			CopyFromTo(leftData, middleData);
			middleData.button = PointerEventData.InputButton.Middle;

			m_MouseState.SetButtonState(PointerEventData.InputButton.Left, StateForMouseButton(0), leftData);
			m_MouseState.SetButtonState(PointerEventData.InputButton.Right, StateForMouseButton(1), rightData);
			m_MouseState.SetButtonState(PointerEventData.InputButton.Middle, StateForMouseButton(2), middleData);

			
			return m_MouseState;
		}
		protected PointerEventData GetMousePointerEventData(int id,bool needRaycastAll)
		{
			// Populate the left button...
			PointerEventData leftData;
			var created = GetPointerData(kMouseLeftId, out leftData, true,id);

			leftData.Reset();

			if (created)
				leftData.position = input.mousePosition;

			Vector2 pos = input.mousePosition;
			if (Cursor.lockState == CursorLockMode.Locked)
			{
				// We don't want to do ANY cursor-based interaction when the mouse is locked
				leftData.position = new Vector2(-1.0f, -1.0f);
				leftData.delta = Vector2.zero;
			}
			else
			{
				leftData.delta = pos - leftData.position;
				leftData.position = pos;
			}
			leftData.scrollDelta = input.mouseScrollDelta;
			leftData.button = PointerEventData.InputButton.Left;
			if (needRaycastAll)
			{
				eventSystem.RaycastAll(leftData, m_RaycastResultCache);
			}
			return leftData;
		}
		protected PointerEventData GetTouchPointerEventDataNextRaycast(PointerEventData pointerData,bool removeInResult = false)
		{
			var raycast = FindFirstRaycast(m_RaycastResultCache);
			pointerData.pointerCurrentRaycast = raycast;
			//m_RaycastResultCache.Clear();
			if (removeInResult)
			{
				m_RaycastResultCache.Remove(raycast);
			}
			return pointerData;
		}
		protected PointerEventData GetTouchPointerEventData(Touch input,int stackId, bool needRaycastAll, out bool pressed, out bool released)
		{
			PointerEventData pointerData;
			var created = GetPointerData(input.fingerId, out pointerData, true, stackId);

			pointerData.Reset();

			pressed = created || (input.phase == TouchPhase.Began);
			released = (input.phase == TouchPhase.Canceled) || (input.phase == TouchPhase.Ended);

			if (created)
				pointerData.position = input.position;

			if (pressed)
				pointerData.delta = Vector2.zero;
			else
				pointerData.delta = input.position - pointerData.position;

			pointerData.position = input.position;

			pointerData.button = PointerEventData.InputButton.Left;

			if (needRaycastAll)
			{
				eventSystem.RaycastAll(pointerData, m_RaycastResultCache);
			}

			
			return pointerData;
		}
	}
}
